package com.lhq.lingsi_study_hall.manager;

import com.google.gson.Gson;
import com.lhq.lingsi_study_hall.common.ErrorCode;
import com.lhq.lingsi_study_hall.exception.BusinessException;
import com.lhq.lingsi_study_hall.utils.ChatCLMUtil;
import com.lhq.lingsi_study_hall.utils.JsonUtils;
import com.zhipu.oapi.ClientV4;
import com.zhipu.oapi.service.v4.model.*;
import io.reactivex.Flowable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.lhq.lingsi_study_hall.constant.AIConstant.STABLE_RANDOM_NUMBER;
import static com.lhq.lingsi_study_hall.constant.AIConstant.UNSTABLE_RANDOM_NUMBER;

/**
 * AI管理器(通用AI调用能力）
 */
@Component
@Slf4j
public  class  AIManager {
    //注入ClientV4客户端
    @Resource
    private ClientV4 client;

    /**
     * 通用请求封装
     * @param messages 消息列表
     * @param isStream 是否流式返回
     * @param temperature 温度值，控制生成内容的随机性
     * @return 返回处理后的字符串
     */
    public String doRequest(List<ChatMessage> messages,Boolean isStream,Float temperature){
        //构建ChatCompletionRequest对象
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildSyncRequest(messages,isStream,temperature);
        return doRequest(chatCompletionRequest);
    }

    public String doRequest(ChatCompletionRequest chatCompletionRequest){
        try {
            //调用模型API并返回结果
            ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest);
            log.info("响应码为: {}",invokeModelApiResp.getCode());
            ModelData data = invokeModelApiResp.getData();
            List<Choice> choices = data.getChoices();
            if (choices==null || choices.size()==0){
                throw new BusinessException(ErrorCode.SYSTEM_ERROR,"模型响应为空");
            }
            log.info("此次消耗的总token为：{}",data.getUsage().getTotalTokens());
            return choices.get(0).getMessage().getContent().toString();
        }catch (Exception e){
            //异常处理
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,e.getMessage());
        }
    }

    public Flowable<ModelData> doStreamRequest(ChatCompletionRequest chatCompletionRequest){
        try {
            //调用模型API并返回结果
            ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest);
            log.info("响应码为: {}",invokeModelApiResp.getCode());
            return invokeModelApiResp.getFlowable();
        }catch (Exception e){
            //异常处理
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,e.getMessage());
        }
    }

    /**
     * 通用请求方法（简化消息传递）
     * @param systemMessage 系统消息
     * @param userMessage 用户消息
     * @param isStream 是否流式返回
     * @param temperature 温度值，控制生成内容的随机性
     * @return 返回处理后的字符串
     */
    public String doRequest(String systemMessage,String userMessage,Boolean isStream,Float temperature){
        //构建消息列表
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildSyncRequest(systemMessage, userMessage, isStream, temperature);
        return doRequest(chatCompletionRequest);
    }


    public  String  doRequest(String systemMessage, String userMessage){
        //构建消息列表
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildSyncStableRequest(systemMessage, userMessage);
        return doRequest(chatCompletionRequest);
    }

    public  Flowable<ModelData>  doStreamRequest(List<ChatMessage> messages, Float temperature){
        //构建消息列表
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildStreamRequest(messages, temperature);
        return doStreamRequest(chatCompletionRequest);
    }

    public  Flowable<ModelData>  doStreamRequest(String systemMessage,String userMessage, Float temperature){
        //构建消息列表
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildStreamRequest(systemMessage, userMessage, temperature);
        return doStreamRequest(chatCompletionRequest);
    }

    public  Flowable<ModelData>  doStreamRequest(String systemMessage,String userMessage){
        //构建消息列表
        return doStreamRequest(systemMessage,userMessage,STABLE_RANDOM_NUMBER);
    }

    public <T>  String doRequestByContext(String systemMessage, String userMessage, int questionNum, Class<T> targetClass){
        //判断题目数量
        if (questionNum<=15){
            return doRequest(systemMessage, userMessage);
        }
        List<String> resultList= new ArrayList<>();
        List<ChatMessage> assistantChatMessageList = new ArrayList<>();
        //当题目数量较多时需要分批调用
        while (questionNum >= 10) {
            invokeAiLoop(10, systemMessage, userMessage, assistantChatMessageList,resultList);
            questionNum = questionNum - 10;
        }
        if (questionNum > 0) {
            invokeAiLoop(questionNum, systemMessage, userMessage, assistantChatMessageList,resultList);
        }
        Gson gson = new Gson();
        return gson.toJson(JsonUtils.mergeJsonLists(resultList, targetClass));
    }

    @Deprecated
    public <T>  String doLoopRequest( int questionNum,String systemMessage, String userMessage, Class<T> targetClass){
        //判断题目数量
        List<String> resultList= new ArrayList<>();
        //当题目数量较多时需要分批调用
        while (questionNum >= 10) {
            invokeAiLoop(10, systemMessage, userMessage,resultList);
            questionNum = questionNum - 10;
        }
        if (questionNum > 0) {
            invokeAiLoop(questionNum, systemMessage, userMessage,resultList);
        }
        Gson gson = new Gson();
        return gson.toJson(JsonUtils.mergeJsonLists(resultList, targetClass));
    }

    /**
     * 不添加上下文的批次调用
     * @param questionNum
     * @param systemMessage
     * @param userMessage
     * @param resultList
     */
    @Deprecated
    private void invokeAiLoop(int questionNum, String systemMessage, String userMessage,
                           List<String> resultList) {
        //重新拼接用户信息模板
        String newUseMessage = replaceSecondLastCount(userMessage, questionNum);
        //每次需要重建request，因为一次调用后socket通道已经被关闭，复用老的 request 会复用老链接会报错
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildSyncStableRequest(systemMessage,newUseMessage);
        String s = doRequest(chatCompletionRequest);
        resultList.add(JsonUtils.captureJsonStr(s));
    }

    /**
     * 添加上下文的分批次调用
     * @param questionNum
     * @param appAiSysMessageConfig
     * @param appAiUserMessageConfig
     * @param assistantChatMessages
     * @param resultList
     */
    private  void invokeAiLoop(int questionNum, String appAiSysMessageConfig, String appAiUserMessageConfig,
                                List<ChatMessage> assistantChatMessages,List<String> resultList) {
        //重新拼接用户信息模板
        String newUseMessage = replaceSecondLastCount(appAiUserMessageConfig, questionNum);
        //每次需要重建request，因为一次调用后socket通道已经被关闭，复用老的 request 会复用老链接会报错
        ChatCompletionRequest chatCompletionRequest = ChatCLMUtil.buildSyncStableRequest(appAiSysMessageConfig,newUseMessage);
        chatCompletionRequest.getMessages().addAll(assistantChatMessages);
        String s = doRequest(chatCompletionRequest);

        //截取字符串
        s= JsonUtils.captureJsonStr(s);
        assistantChatMessages.add(new ChatMessage(ChatMessageRole.ASSISTANT.value(),s));
        resultList.add(s);
    }


    /**
     * 通用同步方法
     * @param systemMessage 系统消息
     * @param userMessage 用户消息
     * @param temperature 温度值，控制生成内容的随机性
     * @return 返回处理后的字符串
     */
    public String doSyncRequest(String systemMessage,String userMessage,Float temperature){
        //调用通用请求方法，不使用流式返回
        return doRequest(systemMessage,userMessage,Boolean.FALSE,temperature);
    }

    /**
     * 通用同步稳定的方法(生成内容稳定)
     * @param systemMessage 系统消息
     * @param userMessage 用户消息
     * @return 返回处理后的字符串
     */
    public String doSyncStableRequest(String systemMessage,String userMessage){
        //调用通用同步方法，使用稳定随机数
        return doRequest(systemMessage,userMessage,Boolean.FALSE,STABLE_RANDOM_NUMBER);
    }

    /**
     * 通用同步不稳定的方法（生成内容天马行空）
     * @param systemMessage 系统消息
     * @param userMessage 用户消息
     * @return 返回处理后的字符串
     */
    public String doSyncUnstableRequest(String systemMessage,String userMessage){
        //调用通用同步方法，使用不稳定随机数
        return doRequest(systemMessage,userMessage,Boolean.FALSE,UNSTABLE_RANDOM_NUMBER);
    }


    /**
     * 替换原始字符串中的倒数第二个数字为新的数量。
     *
     * @param originalString 原始字符串
     * @param newCount       用户请求的新数量
     * @return 更新后的字符串
     */
    public static String replaceSecondLastCount(String originalString, int newCount) {
        // 正则表达式来匹配所有的数字序列
        String regex = "\\d+";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(originalString);

        // 存储匹配到的数字的位置
        List<Integer> numberPositions = new ArrayList<>();
        while (matcher.find()) {
            numberPositions.add(matcher.start());
        }

        // 检查是否有足够的数字进行替换
        if (numberPositions.size() < 2) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"原始字符串中没有足够的数字来进行替换");
        }

        // 获取倒数第二个数字的起始位置
        int secondLastPosition = numberPositions.get(numberPositions.size() - 2);

        // 找到该数字的结束位置（即下一个非数字字符或字符串末尾）
        int endPosition = originalString.length();
        for (int i = secondLastPosition + 1; i < originalString.length(); i++) {
            if (!Character.isDigit(originalString.charAt(i))) {
                endPosition = i;
                break;
            }
        }

        // 构建新的字符串，用新数量替换倒数第二个数字
        return originalString.substring(0, secondLastPosition)
                + newCount
                + originalString.substring(endPosition);
    }
}
